function hasCircularDependency(obj){
    let visited = new Set() // 表示已经访问过的节点
    let stack = new Set()
    // 深搜
    const dfs = (node) => {
        // 如果发现，则立刻终止，返回true
        // 即如果发现了一个节点在栈中，说明有环
        if(stack.has(node))
            return true
        // 如果已经访问过，则不再访问，返回false
        if(visited.has(node))
            return false
        visited.add(node)
        stack.add(node)
        if(obj[node]){
            const deps = obj[node].deps || []
            for(let dep of deps){
                if(dfs(dep))
                    return true
            }
        }
        // 从栈中删除
        stack.delete(node)
        return false
    }
    // 从obj的所有属性开始深搜，每个属性当成一次起点
    for(let node in obj){
        if(dfs(node))
            return true
    }
    return false
}

console.log(hasCircularDependency({
    a: {deps: ['b', 'd']},
    b: {deps: ['c']},
    c: {deps: []}
})) // true
